#include "app_serial.h"
#include "app/app_device.h"
#include <termios.h>


static int app_serial_setRaw(SerialDevice *serial_device)
{
    struct termios options;
    if(tcgetattr(serial_device->super.fd, &options) != 0)
    {
        return -1;
    }

    // 设置串口为原始模式
    cfmakeraw(&options);

    return tcsetattr(serial_device->super.fd, TCSAFLUSH, &options);
}
int app_serial_init(SerialDevice *serial_device, char *filename)
{
    if(app_device_init(&serial_device->super, filename) < 0)
    {
        return -1;
    }
    // 设置串口的数据位为8bits
    struct termios options;
    // 获取串口的属性
    if(tcgetattr(serial_device->super.fd, &options) != 0)
    {
        return -1;
    }

    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    tcsetattr(serial_device->super.fd, TCSAFLUSH , &options);
    app_serial_setRaw(serial_device);
    app_serial_setBaudRate(serial_device, SERIAL_BUAD_RATE_115200);
    app_serial_setParity(serial_device, PARITY_NONE);
    app_serial_setStopBits(serial_device, STOP_BITS_ONE);
    app_serial_setBlockMode(serial_device, 0);
    // 刷下串口，新设置起效
    app_serial_flush(serial_device);
    return 0;
}

int app_serial_setBaudRate(SerialDevice *serial_device, SerialBaudRate baud_rate)
{
    struct termios options;
    // 获取串口的属性
    if(tcgetattr(serial_device->super.fd, &options) != 0)
    {
        return -1;
    }
    // 设置串口的波特率
    switch (baud_rate) {
        case SERIAL_BUAD_RATE_9600:
            cfsetispeed(&options, B9600);
            cfsetospeed(&options, B9600);
            break;
        case SERIAL_BUAD_RATE_115200:
            cfsetispeed(&options, B115200);
            cfsetospeed(&options, B115200);
            break;
        default:
            break;
    }
    // 把属性写回串口
    return tcsetattr(serial_device->super.fd, TCSAFLUSH , &options);
}

int app_serial_setStopBits(SerialDevice *serial_device, StopBits stop_bits)
{
    struct termios options;
    // 获取串口的属性
    if(tcgetattr(serial_device->super.fd, &options) != 0)
    {
        return -1;
    }

    options.c_cflag &= ~CSTOPB;
    options.c_cflag |= stop_bits;
    return tcsetattr(serial_device->super.fd, TCSAFLUSH , &options);
}
int app_serial_setParity(SerialDevice *serial_device, Parity parity)
{
     struct termios options;
    // 获取串口的属性
    if(tcgetattr(serial_device->super.fd, &options) != 0)
    {
        return -1;
    }

    options.c_cflag &= ~(PARENB | PARODD);
    options.c_cflag |= parity;

    return tcsetattr(serial_device->super.fd, TCSAFLUSH , &options);
}
int app_serial_flush(SerialDevice * serial_device)
{
    return tcflush(serial_device->super.fd, TCIOFLUSH);
}

int app_serial_setBlockMode(SerialDevice *serial_device, int block_mode)
{
    struct termios options;
    // 获取串口的属性
    if(tcgetattr(serial_device->super.fd, &options) != 0)
    {
        return -1;
    }

    if(block_mode)
    {
        // 阻塞模式
        options.c_cc[VTIME] = 0;
        options.c_cc[VMIN] = 1;

    } else {
        // 非阻塞模式
        options.c_cc[VTIME] = 5;
        options.c_cc[VMIN] = 0;
    }

    return tcsetattr(serial_device->super.fd, TCSAFLUSH , &options);
}
